package mobi.zeedev.flyingsaucer.scala.delegates


import org.sgine.property.container.PropertyContainer
import org.apache.http.cookie.Cookie
import org.apache.http.impl.cookie.BasicClientCookie
import java.util.{Calendar, List, Date}
import org.apache.http.impl.client.BasicCookieStore
import org.apache.http.client.CookieStore
import mobi.zeedev.flyingsaucer.common.CredentialsModule.impl.SHA1
import java.io.UnsupportedEncodingException
import java.security.NoSuchAlgorithmException
import roboguice.util.Ln
import java.lang.Boolean
import org.sgine.property.{MutableProperty, DependentProperty, AdvancedProperty}

//import mobi.zeedev.java.experimental.ICredentials

import reflect.{BeanInfo, BooleanBeanProperty, BeanProperty}
import mobi.zeedev.flyingsaucer.common.CredentialsModule.interfaces.ICredentials

@BeanInfo
class PropertyCredentialsImpl extends ICredentials with PropertyContainer {

  //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  // Constructor
  //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  //???

  def init: Unit = {

    //  loggedIn

  }

  //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  // Hack Setters
  //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  override def setUfoNonMember(valIn: java.lang.Boolean): Unit = {
    ufoNonMember.set(valIn)
  }

  override def setUfoMouMember(valIn: java.lang.Boolean): Unit = {
    ufoMouMember.set(valIn)
  }

  override def setMemberId(valIn: java.lang.Integer): Unit = {
    memberId.set(valIn)
  }

  override def setStoreNumber(valIn: String): Unit = {
    storeNumber.set(valIn)
  }

  override def setUfoRemember(valIn: java.lang.Boolean): Unit = {
    ufoRemember.set(valIn)
  }

  override def setOriginDate(valIn: Date): Unit = {
    originDate.set(valIn)
  }

  override def setDBId(valIn: java.lang.Integer): Unit = {
    DBId.set(valIn)
  }

  override def setCardNumber(valIn: java.lang.String): Unit = {
    cardNumber.set(valIn)
  }

  override def setUfoAutoLogin(valIn: java.lang.Boolean): Unit = {
    ufoAutoLogin.set(valIn)
  }

  override def setUserName(valIn: java.lang.String): Unit = {
    userName.set(valIn)
  }

  override def setPasswordHash(valIn: java.lang.String): Unit = {
    passwordHash.set(valIn)
  }

  //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  // Bean Properties
  //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  @BeanProperty
  val password = new AdvancedProperty[java.lang.String]("")

  @BeanProperty
  val userName = new AdvancedProperty[String]("")

  @BeanProperty
  val DBId = new AdvancedProperty[java.lang.Integer](0)

  @BeanProperty
  val passwordHash = new AdvancedProperty[String]("")

  @BeanProperty
  val ufoAutoLogin = new AdvancedProperty[java.lang.Boolean](false)

  @BeanProperty
  val cardNumber = new AdvancedProperty[String]("")

  @BeanProperty
  val ufoRemember = new AdvancedProperty[java.lang.Boolean](false)

  @BeanProperty
  val ufoNonMember = new AdvancedProperty[java.lang.Boolean](false)

  @BeanProperty
  val ufoMouMember = new AdvancedProperty[java.lang.Boolean](false)

  @BeanProperty
  val storeNumber = new AdvancedProperty[String]("")

  @BeanProperty
  val memberId = new AdvancedProperty[java.lang.Integer](0)

  @BeanProperty
  val originDate = new AdvancedProperty[java.util.Date](null)

  //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  // Boolean Bean Properties
  //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  @BooleanBeanProperty
  val masterRefreshCompletedWithLogin = new MutableProperty[java.lang.Boolean] with DependentProperty[java.lang.Boolean] {
    protected def dependency: () => java.lang.Boolean = {
      (loggedIn.value.booleanValue && hasMemberId.booleanValue && hasOriginDate.booleanValue).booleanValue
    }
  }
  @BooleanBeanProperty
  val downloadPairComplete = new MutableProperty[java.lang.Boolean] with DependentProperty[java.lang.Boolean] {
    protected def dependency: () => java.lang.Boolean = {
      (loggedIn.value.booleanValue && hasMemberId.booleanValue).booleanValue
    }
  }
  @BooleanBeanProperty
  val loginAvailable = new MutableProperty[java.lang.Boolean] with DependentProperty[java.lang.Boolean] {
    protected def dependency: () => java.lang.Boolean = {
      var res: Boolean = !isNullOrEmpty(storeNumber.value) && !isNullOrEmpty(cardNumber.value) && !isNullOrEmpty(password.value)
      return res.booleanValue
    }
  }
  @BooleanBeanProperty
  val loggedIn = new MutableProperty[java.lang.Boolean] with DependentProperty[java.lang.Boolean] {
    protected def dependency: () => java.lang.Boolean = {
      var res: Boolean = !isNullOrEmpty(password.value) && !isNullOrEmpty(storeNumber.value) && !isNullOrEmpty(userName.value) && !isNullOrEmpty(cardNumber.value)
      res.booleanValue
    }
  }
  //  {

  //    val dependency = {
  //      var res: Boolean = !isNullOrEmpty(password.value) && !isNullOrEmpty(storeNumber.value) && !isNullOrEmpty(userName.value) && !isNullOrEmpty(cardNumber.value)
  //      res.booleanValue
  ////      val res2 : java.lang.Boolean = res
  ////
  ////      res2
  //    }

  //  }

  //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  // MetaData
  //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  def getLoginParams: java.util.Map[String, String] = {

    val m: java.util.Map[String, String] = new java.util.HashMap[String, String](5)

    //    var m: Map[String, String] = new HashMap[String, String](5)

    m.put("card_number", cardNumber.value)

    m.put("password", password.value)

    m.put("store", storeNumber.value)

    m.put("f", "Login")

    m.put("cookie", "true")

    if (ufoMouMember.value != null && ufoMouMember.value.booleanValue) {
      m.put("mou", "true")
    }

    m

  }

  def reset: Unit = {

    storeNumber := ""

    cardNumber := ""

    password := ""

    passwordHash := ""

    userName := ""

    memberId := 0

    DBId := 0

    ufoRemember := false

    ufoAutoLogin := false

    ufoMouMember := false

    originDate := null

    ufoNonMember := false

  }

  //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  // Properties / Attributes (things that describe the state/condition of credentials)
  //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  override def setPassword(loginPassword: String): Unit = {
    password := loginPassword

    try {
      passwordHash := SHA1.getSHA1(password.value)
    }
    catch {

      case e: NoSuchAlgorithmException => {
        Ln.e(e)
        passwordHash := ""
      }
      case e: UnsupportedEncodingException => {
        Ln.e(e)
        passwordHash := ""
      }

    }

  }


  def permittedLogin: java.lang.Boolean = {
    return (ufoAutoLogin.value.booleanValue && (loggedIn.value.booleanValue || loginAvailable.value.booleanValue) && ufoRemember.value.booleanValue)
  }

  def hasOriginDate: java.lang.Boolean = {
    return !isNullOrEmpty(originDate.value)
  }

  def hasMemberId: java.lang.Boolean = {
    return !isNullOrEmpty(memberId.value)
  }

  def generateCookieInfo: List[Cookie] = {

    var cookieList: Array[String] = Array("card", getCardNumber, "store", getStoreNumber, "hash", getPasswordHash, "user", getEscapedEmail(getUserName))

    var cs: CookieStore = new BasicCookieStore()

    var i: Int = 0
    while (i < cookieList.length - 1) {

      var bcc: BasicClientCookie = new BasicClientCookie(cookieList(i), cookieList(i + 1))
      bcc.setVersion(0)
      bcc.setDomain(".beerknurd.com")
      bcc.setPath("/")
      var c: Calendar = Calendar.getInstance
      c.add(Calendar.YEAR, 1)
      bcc.setExpiryDate(c.getTime)
      cs.addCookie(bcc)

      i = i + 2
    }


    cs.getCookies

  }

  //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  // Utility Functions
  //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  private def getEscapedEmail(in: String): String = {
    var ret: String = null
    if (!isNullOrEmpty(in)) {
      ret = in.replace("@", "%40")
    }
    //    return ret
    //    val ret = Uri.encode(in);
    ret
  }

  private def isNullOrEmpty(r: AnyRef): scala.Boolean = {
    return if ((r == null)) true else r.toString.equals("")
  }


}